package easybooking.report;

import java.util.*;
import java.rmi.*;
import easybooking.FlightManagement;
import easybooking.data.*;
import java.rmi.server.UnicastRemoteObject;

/**
 * Implementation of the <code>ReportGenerator</code>-Interface.
 *
 * @see ReportGenerator
 * @author Hakan Keles
 */
// <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
// #[regen=yes,id=DCE.981BF5DC-D899-18A9-E0AD-F436838C76F3]
// </editor-fold> 
public class ReportGeneratorImpl extends UnicastRemoteObject implements ReportGenerator {

    /*
     * A Report Generator needs access to the FlightManagement. The FlightManagement provides
     * important methods about the coexistence of data-objects.
     */
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.23AACD38-3FA9-A340-CE7E-49E0506CF26C]
    // </editor-fold> 
    private FlightManagement FlightManagement = null;

    /*
     * Get the FlightManagement(internal usage)
     * @return A FlightManagement-Object
     */
    protected FlightManagement getFlightManagement() {
        return this.FlightManagement;
    }

    /**
     * Every ReportGenerator needs an access to the FlightManagament, whose declaration is already enforced
     * at the instantiation of the Generator through the constructor.
     *
     * @param fm the FlightManagement
     * @throws RemoteException
     * @see FlightManagement
     */
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.94810196-6C67-38A7-3C79-57988F6F6900]
    // </editor-fold> 
    public ReportGeneratorImpl(FlightManagement fm) throws RemoteException {
        this.FlightManagement = fm;
    }

    protected void addImprint(Report r) {

        /*
         * Das Impressum soll wesentliche Informationen über die Bank enthalten.
         */
        FlightManagement = this.getFlightManagement();

        /*
         * Das Imressum soll mehrzeilig sein.
         */
        CompositeParagraph imprint = new CompositeParagraph();

        imprint.addSubParagraph(new SimpleParagraph("EasyBooking Systems"));
        imprint.addSubParagraph(new SimpleParagraph("service@eb.net"));


        // Das eigentliche Hinzufügen des Impressums zum Report.
        r.setImprint(imprint);



    }

    /**
     * Generates a <code>AllFlightsOfCustomerWithAirlineReport</code>-Report. These report displays all
     * flights of a certain customer with a certain airline.
     *
     * @param c Association to the customer, whose flights are displayed.
     * @param a Association to the airline, which is part of the flight.
     * @return the result report object
     * @throws java.rmi.RemoteException
     * @see AllFlightsOfCustomerWithAirlineReport
     */
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.3328D82A-F664-1579-F9BC-8A669B3B3EF1]
    // </editor-fold> 
    public AllFlightsOfCustomerWithAirlineReport createFlightsOfCustomerWithAirlineReport(Customer c, Airline a) throws java.rmi.RemoteException {
        AllFlightsOfCustomerWithAirlineReport result = new AllFlightsOfCustomerWithAirlineReport();
        result.setTitle("All flights of a customer with an airline:");
        result.setDateTime(new Date());
        this.addImprint(result);
        CompositeParagraph header = new CompositeParagraph();


        try {
            header.addSubParagraph(new SimpleParagraph(c.getLastname() + ", " + c.getFirstname()));
            header.addSubParagraph(new SimpleParagraph("Customer-No.: " + c.getCustomerId()));
        } catch (RemoteException e) {
            header.addSubParagraph(new SimpleParagraph(e.toString()));
        }

        result.setHeader(header);

        try {
            Row headline = new Row();
            headline.addColumn(new Column("Flight-No."));
            headline.addColumn(new Column("Date"));
            headline.addColumn(new Column("Plane"));
            headline.addColumn(new Column("Start"));
            headline.addColumn(new Column("Dest."));
            headline.addColumn(new Column("Airline"));
            result.addRow(headline);

            Vector<Flight> flights = this.FlightManagement.findFlightByCustomerAndAirline(c, a);

            for (Flight f : flights) {

                Row flightRow = new Row();
                flightRow.addColumn(new Column(String.valueOf(a.getInitials() + f.getFlightId())));
                flightRow.addColumn(new Column(String.valueOf(f.getDateTime())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findPlaneByKey(f.getPlaneId()).getName())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirportByKey(f.getStartAirportId()).getName())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirportByKey(f.getDestAirportId()).getName())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirlineByKey(a.getAirlineId()).getName())));
                result.addRow(flightRow);
            }
        } catch (RemoteException e1) {
            Row error = new Row();
            error.addColumn(new Column("Error adding new column!"));
            error.addColumn(new Column(e1.toString()));
            result.addRow(error);
        }
        return result;
    }

    /**
     * Generates a <code>AllFlightsOfCustomerWithAirlineReport</code>-Report. These report displays all
     * flights of a certain customer with a certain airline.
     *
     * @param c Association to the customer, whose flights are displayed.
     * @param a Association to the airline, which is part of the flight.
     * @param from 
     * @param to
     * @return the result report object
     * @throws java.rmi.RemoteException
     * @see AllFlightsOfCustomerWithAirlineReport
     */
    public AllFlightsOfCustomerWithAirlineReport createFlightsOfCustomerWithAirlineReport(Customer c, Airline a, Date from, Date to) throws java.rmi.RemoteException {
        AllFlightsOfCustomerWithAirlineReport result = new AllFlightsOfCustomerWithAirlineReport();
        result.setTitle("All flights of a customer with an airline:");
        result.setDateTime(new Date());
        this.addImprint(result);
        CompositeParagraph header = new CompositeParagraph();


        try {
            header.addSubParagraph(new SimpleParagraph(c.getLastname() + ", " + c.getFirstname()));
            header.addSubParagraph(new SimpleParagraph("Customer-No.: " + c.getCustomerId()));
        } catch (RemoteException e) {
            header.addSubParagraph(new SimpleParagraph(e.toString()));
        }

        result.setHeader(header);

        try {
            Row headline = new Row();
            headline.addColumn(new Column("Flight-No."));
            headline.addColumn(new Column("Date"));
            headline.addColumn(new Column("Plane"));
            headline.addColumn(new Column("Start"));
            headline.addColumn(new Column("Dest."));
            headline.addColumn(new Column("Airline"));
            result.addRow(headline);

            Vector<Flight> flights = this.FlightManagement.findFlightByCustomerAndAirlineAndPeriod(c, a, from, to);

            for (Flight f : flights) {

                Row flightRow = new Row();
                flightRow.addColumn(new Column(String.valueOf(a.getInitials() + f.getFlightId())));
                flightRow.addColumn(new Column(String.valueOf(f.getDateTime())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findPlaneByKey(f.getPlaneId()).getName())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirportByKey(f.getStartAirportId()).getName())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirportByKey(f.getDestAirportId()).getName())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirlineByKey(a.getAirlineId()).getName())));
                result.addRow(flightRow);
            }
        } catch (RemoteException e1) {
            Row error = new Row();
            error.addColumn(new Column("Error adding new column!"));
            error.addColumn(new Column(e1.toString()));
            result.addRow(error);
        }
        return result;
    }

    /**
     * Generates a <code>FlightSeatingReport</code>-Report. These report displays a seating of a flight.
     *
     * @param f Association to the flight, whose seating is displayed.
     * @return the result report object
     * @throws java.rmi.RemoteException
     * @see FlightSeatingReport
     */
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.36B207DA-9AA0-5DD4-3B64-915F2D81BA24]
    // </editor-fold> 
    public FlightSeatingReport createFlightSeatingReport(Flight f) throws RemoteException {
        FlightSeatingReport result = new FlightSeatingReport();
        result.setTitle("Seating:");
        result.setDateTime(new Date());
        this.addImprint(result);
        CompositeParagraph header = new CompositeParagraph();

        try {
            Plane p = this.FlightManagement.findPlaneByKey(f.getPlaneId());
            Airline airl = this.FlightManagement.findAirlineByKey(p.getAirlineId());
            header.addSubParagraph(new SimpleParagraph("Flight-No.: " + airl.getInitials() + f.getFlightId()));
        } catch (RemoteException e) {
            header.addSubParagraph(new SimpleParagraph(e.toString()));
        }

        result.setHeader(header);
        try {
            Plane p = this.FlightManagement.findPlaneByKey(f.getPlaneId());
            Type t = this.FlightManagement.findTypeByKey(p.getTypeId());

            Row headline = new Row();
            headline.addColumn(new Column("Row"));
            for (int k = 1; k <= t.getColumns(); k++) {
                char seat = (char) ('A' + k - 1);
                headline.addColumn(new Column("Seat " + seat));
            }
            result.addRow(headline);
            Vector<Seat> bookedSeats = this.FlightManagement.findBookedSeatByFlight(f.getFlightId());
            Vector<Seat> allSeats = this.FlightManagement.findSeatByPlane(p.getPlaneId());
            Vector<Seat> boSeats = new Vector();


            Iterator si = allSeats.iterator();
            Iterator bsi = bookedSeats.iterator();

            while (bsi.hasNext()) {
                Seat bs = (Seat) bsi.next();
                while (si.hasNext()) {
                    Seat s = (Seat) si.next();
                    System.out.println(s.getSeatId() + "==" + bs.getSeatId());
                    if (s.getSeatId() == bs.getSeatId()) {
                        boSeats.add(s);
                        System.out.println("Booked Seat: " + s.getSeatId());
                        break;

                    }
                }

            }

            Row seatRow = null;

            Iterator asi = allSeats.iterator();
            while (asi.hasNext()) {
                Seat s = (Seat) asi.next();

                if (s.getSeat() == 'A') {
                    if (seatRow != null) {
                        result.addRow(seatRow);
                    }
                    seatRow = new Row();
                    seatRow.addColumn(new Column(String.valueOf(s.getRow())));
                }
                if (boSeats.contains(s)) {
                    seatRow.addColumn(new Column(String.valueOf("X")));
                } else {
                    seatRow.addColumn(new Column(String.valueOf("")));
                }

            }
            result.addRow(seatRow);

        } catch (RemoteException e1) {
            Row error = new Row();
            error.addColumn(new Column("Error adding new column!"));
            error.addColumn(new Column(e1.toString()));
            result.addRow(error);
        }
        return result;
    }

    /**
     * Generates a <code>AllFlightsOfCustomerReport</code>-Report. These report displays all
     * flights of a certain customer.
     *
     * @param c Association to the customer, whose flights are displayed.
     * @return the result report object
     * @throws java.rmi.RemoteException
     * @see AllFlightsOfCustomerReport
     */
// <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
// #[regen=yes,id=DCE.65EDBD99-1DAB-D054-6076-783AFA0459AC]
// </editor-fold> 
    public AllFlightsOfCustomerReport createAllFlightsOfCustomerReport(
            Customer c) throws RemoteException {
        AllFlightsOfCustomerReport result = new AllFlightsOfCustomerReport();
        result.setTitle("All flights of a customer:");
        result.setDateTime(new Date());
        this.addImprint(result);
        CompositeParagraph header = new CompositeParagraph();

        try {
            header.addSubParagraph(new SimpleParagraph(c.getLastname() + ", " + c.getFirstname()));
            header.addSubParagraph(new SimpleParagraph("Customer-No.: " + c.getCustomerId()));
        } catch (RemoteException e) {
            header.addSubParagraph(new SimpleParagraph(e.toString()));
        }

        result.setHeader(header);

        try {
            Row headline = new Row();
            headline.addColumn(new Column("Flight-No."));
            headline.addColumn(new Column("Date"));
            headline.addColumn(new Column("Plane"));
            headline.addColumn(new Column("Start"));
            headline.addColumn(new Column("Dest."));
            headline.addColumn(new Column("Airline"));

            result.addRow(headline);

            Vector<Flight> flights = this.FlightManagement.getAllFlightsOfCustomer(c);

            for (Flight f : flights) {
                Row flightRow = new Row();
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirlineByKey(f.getPlaneId()).getInitials() + f.getFlightId())));
                flightRow.addColumn(new Column(String.valueOf(f.getDateTime())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findPlaneByKey(f.getPlaneId()).getName())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirportByKey(f.getStartAirportId()).getName())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirportByKey(f.getDestAirportId()).getName())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirlineByKey(f.getPlaneId()).getName())));
                this.FlightManagement.findPlaneByKey(f.getPlaneId()).getName();
                result.addRow(flightRow);
            }

        } catch (RemoteException e1) {
            Row error = new Row();
            error.addColumn(new Column("Error adding new column!"));
            error.addColumn(new Column(e1.toString()));
            result.addRow(error);
        }

        return result;
    }

    /**
     * Generates a <code>AllFlightsOfCustomerReport</code>-Report. These report displays all
     * flights of a certain customer.
     *
     * @param c Association to the customer, whose flights are displayed.
     * @param from Start date of the period
     * @param to Stop date of the period
     * @return the result report object
     * @throws java.rmi.RemoteException
     * @see AllFlightsOfCustomerReport
     */
    public AllFlightsOfCustomerReport createAllFlightsOfCustomerReport(
            Customer c, Date from, Date to) throws RemoteException {
        AllFlightsOfCustomerReport result = new AllFlightsOfCustomerReport();
        result.setTitle("All flights of a customer:");
        result.setDateTime(new Date());
        this.addImprint(result);
        CompositeParagraph header = new CompositeParagraph();

        try {
            header.addSubParagraph(new SimpleParagraph(c.getLastname() + ", " + c.getFirstname()));
            header.addSubParagraph(new SimpleParagraph("Customer-No.: " + c.getCustomerId()));
        } catch (RemoteException e) {
            header.addSubParagraph(new SimpleParagraph(e.toString()));
        }

        result.setHeader(header);

        try {
            Row headline = new Row();
            headline.addColumn(new Column("Flight-No."));
            headline.addColumn(new Column("Date"));
            headline.addColumn(new Column("Plane"));
            headline.addColumn(new Column("Start"));
            headline.addColumn(new Column("Dest."));
            headline.addColumn(new Column("Airline"));

            result.addRow(headline);

            Vector<Flight> flights = this.FlightManagement.findFlightByCustomerAndPeriod(c, from, to);

            for (Flight f : flights) {
                Row flightRow = new Row();
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirlineByKey(f.getPlaneId()).getInitials() + f.getFlightId())));
                flightRow.addColumn(new Column(String.valueOf(f.getDateTime())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findPlaneByKey(f.getPlaneId()).getName())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirportByKey(f.getStartAirportId()).getName())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirportByKey(f.getDestAirportId()).getName())));
                flightRow.addColumn(new Column(String.valueOf(this.FlightManagement.findAirlineByKey(f.getPlaneId()).getName())));
                this.FlightManagement.findPlaneByKey(f.getPlaneId()).getName();
                result.addRow(flightRow);
            }

        } catch (RemoteException e1) {
            Row error = new Row();
            error.addColumn(new Column("Error adding new column!"));
            error.addColumn(new Column(e1.toString()));
            result.addRow(error);
        }

        return result;
    }
}

